/**
 * 
 */
package edu.hawaii.stack.page;

import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.model.PropertyModel;
import edu.hawaii.stack.Stack;

/**
 * A page for using and displaying a stack.
 * 
 * @author Aric West
 */
public class StackPage extends WebPage {
  /** Support serialization. */
  private static final long serialVersionUID = 1L;
  
  /**
   * Constructor containing most of the logical set up for the page.  Defines a text field, push,
   * pop, and clear buttons, and a table displaying the current contents of the stack.  Pushing a
   * null value or popping an empty stack are illegal. 
   */
  public StackPage() {
    Form stackForm = new Form("stackForm");
    stackForm.add(new TextField("inputField", 
        new PropertyModel(getSession(), "inputField")));
    stackForm.add(new Button("popButton") {
      private static final long serialVersionUID = 1L;
      
      /**
       * Pop the stack.
       */
      @Override
      public void onSubmit() {
        try {
          setInputField(getStack().pop().toString());
          setResponsePage(StackPage.class);
        }
        catch (Exception e) {
          setInputField("No element to pop.");
        }
      }
    });
    stackForm.add(new Button("pushButton") {
      private static final long serialVersionUID = 1L;
      
      /**
       * Push an element onto the stack.
       */
      @Override
      public void onSubmit() {
        if (getInputField() == null) {
          setInputField("Cannot push an empty field.");
          setResponsePage(StackPage.class);
        }
        else {
          getStack().push(getInputField());
          setInputField("");
          setResponsePage(StackPage.class);
        }
      }
    });
    stackForm.add(new Button("clearButton") {
      private static final long serialVersionUID = 1L;
      
      /**
       * Clear the stack.
       */
      @Override
      public void onSubmit() {
        getStack().clear();
        setInputField("");
        setResponsePage(StackPage.class);
      }
    }); 
    add(stackForm);
    
    //Create table showing entire stack.
    List<Object> stackElements = new ArrayList<Object>();
    Object[] stackArray = getStack().toArray();
    // Reverses the elements of the stack so it will put new items at the top of the table.
    for (int i = stackArray.length - 1; i >= 0; i--) {
      stackElements.add(stackArray[i]);
    }
    DataView stackTable = new DataView("stackTable", new ListDataProvider(stackElements)) {
      /** For serialization. */
      private static final long serialVersionUID = 1L;

      /**
       * Display each row in the table.
       * 
       * @param item A element to be displayed.
       */
      @Override
      public void populateItem(Item item) {
        String element = (String) item.getModelObject();
        item.add(new Label("Element", element));
      }
    };
    add(stackTable);
  }

  /**
   * Returns the session instance associated with the current user.
   * 
   * @return The StackSession.
   */
  public StackSession getStackSession() {
    return (StackSession) getSession();
  }
  
  /**
   * Accessor to stack for this session.
   * 
   * @return This session's stack.
   */
  public Stack getStack() {
    return getStackSession().getStack();
  }
  
  /**
   * Accessor to input field for this session.
   * 
   * @return This session's input field value.
   */
  public String getInputField() {
    return getStackSession().getInput();
  }

  /**
   * Setter for input field for this session.
   * 
   * @param input The new input field value.
   */
  public void setInputField(String input) {
    getStackSession().setInput(input);
  }  
}
